package com.lichuang.dedao.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lichuang.dedao.user.entity.Follow;
import com.lichuang.dedao.user.entity.User;
import com.lichuang.dedao.user.mapper.UserMapper;
import com.lichuang.dedao.user.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lichuang.dedao.user.utils.SmsUtil;
import com.lichuang.dedao.user.utils.TokenUtil;
import com.lichuang.dedao.user.vo.UserVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CachePut;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 用户 服务实现类
 * </p>
 *
 * @author hanghang
 * @since 2019-07-12
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Value("${custom.redis.codekey.prefix}")
    private String codeKeyPrefix;

    @Value("${custom.redis.codekey.timeout}")
    private long codeKeyTimeOut;

    @Value("${custom.redis.userkey.prefix}")
    private String userKeyPrefix;

    @Value("${custom.redis.userkey.timeout}")
    private long userKeyTimeOut;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private FollowServiceImpl followService;

    @Autowired
    private UserCouponServiceImpl userCouponService;

    @Override
    public void sendSms(String phone) {
        // 生成4位随机数
        Integer code = (int) ((Math.random() * 9 + 1) * 1000);
        String codeKey = codeKeyPrefix + "::" + phone;
        // 如果redis中没有对应的key就存入缓存，并返回true；如果已经存在则不保存，并返回false
        boolean isSet = redisTemplate.opsForValue().setIfAbsent(codeKey, code, Duration.ofMinutes(codeKeyTimeOut));
        if (isSet == false) {
            return;
        }
        SmsUtil.sendSms(phone, code);
    }

    @Override
    public boolean validationCode(String phone, Integer newCode) {
        String code = (String) redisTemplate.opsForValue().get(codeKeyPrefix + "::" + phone);
        if (code != null && Integer.valueOf(code) != newCode) {
            return true;
        }
        return false;
    }

    @Override
    public User loginAndRegistry(String phone, HttpServletResponse response) {
        User userParam = new User();
        userParam.setUserPhone(phone);
        QueryWrapper queryWrapper = new QueryWrapper(userParam);
        User user = baseMapper.selectOne(queryWrapper);
        if (user == null) {
            // user为空代表数据库中不存在，需要插入一条数据
            userParam.setNickName(userParam.getUserPhone());
            userParam.setCreateTime(LocalDateTime.now());
            Integer count = baseMapper.insert(userParam);
            if (count >= 1) {
                user = userParam;
                // 给用户发放优惠券
                userCouponService.issueCoupon(user.getUserId(), 1, LocalDate.now().plusMonths(3));
            }
        }
        saveUserWithRedisAndSaveTokenWithCookie(user, response);
        return user;
    }

    @Override
    public User loginWithPassword(User userParam) {
        QueryWrapper queryWrapper = new QueryWrapper(userParam);
        return baseMapper.selectOne(queryWrapper);
    }

    @Override
    public User getCurrentLoginUser(String loginToken) {
        return (User) redisTemplate.opsForValue().get(userKeyPrefix + "::" + loginToken);
    }

    @Override
    public UserVO showUserInfo(String loginToken) {
        User user = getCurrentLoginUser(loginToken);
        UserVO userVO = UserVO.transferVo(user);
        return userVO;
    }

    @Override
    public void saveUserWithRedisAndSaveTokenWithCookie(User user, HttpServletResponse response) {
        String loginToken = TokenUtil.produceUUIDWithoutLine();
        String userKey = userKeyPrefix + "::" + loginToken;
        redisTemplate.opsForValue().set(userKey, user, Duration.ofDays(userKeyTimeOut));
        saveTokenWithCookie(loginToken, response);
    }

    @Override
    public void saveTokenWithCookie(String loginToken, HttpServletResponse response) {
        Cookie cookie = new Cookie("loginToken", loginToken);
        cookie.setPath("/");
        // 秒为单位，30天
        cookie.setMaxAge(2592000);
        response.addCookie(cookie);
    }

    @Override
    @CachePut(cacheNames = "user", key = "#token")
    public User updateUserWithRedis(User user, String token) {
        user.setUserId(getCurrentLoginUser(token).getUserId());
        user.setUpdateTime(LocalDateTime.now());
        baseMapper.updateById(user);
        return baseMapper.selectById(user.getUserId());
    }

    @Override
    public User selectUserById(Integer id) {
        return baseMapper.selectById(id);
    }

    @Override
    public List<User> selectFollowedUser(Integer userId) {
        List<Follow> follows = followService.selectFollowedByUserId(userId);
        List<User> followedUsers = new ArrayList<>();
        for (Follow follow : follows) {
            Integer followedUserId = follow.getFollowedUserId();
            User followedUser = selectUserById(followedUserId);
            followedUsers.add(followedUser);
        }
        return followedUsers;
    }

    @Override
    public List<User> selectFollowerUser(Integer userId) {
        List<Follow> follows = followService.selectFollowerByUserId(userId);
        List<User> followerUsers = new ArrayList<>();
        for (Follow follow : follows) {
            Integer followerUserId = follow.getUserId();
            User followerUser = selectUserById(followerUserId);
            followerUsers.add(followerUser);
        }
        return followerUsers;
    }


}
